home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Belgian Amiga Club - ADF Collection
/
BS1 part 60.zip
/
BS1 part 60
/
Kick Pascal v2.10 d2.adf
/
DEMO
/
3D.backup
< prev
next >
Wrap
Text File
|
1990-11-04
|
17KB
|
418 lines
PROGRAM _3D;
{ geschrieben von: Michael Janich 1989 }
{ bearbeitet von: Jens "Himpelsoft" Gelhar }
{ ALL RIGHTS REVERSED. }
{ Programm wird mit ESC beendet. }
{ Mit den Cursortasten kann man die Rotationsrichtung des }
{ Objekts ändern, mit einigen Tasten des Ziffernblocks }
{ den Standpunkt des Betrachters. }
{ In der vorliegenden Version gibt es noch Fehler, wenn }
{ Linien den Bildschirmrand überschreiten. }
CONST width=640;
height=256; { Screen }
file_name = 'KP-DEMOS:Demo/3D_coords/coords.haus';
{ Aus dieser Datei werden die Koordinaten gelesen }
rot_angle=0.12; { rotation in one step }
{$incl "Intuition.lib","Graphics.lib" }
TYPE Point = REAL;
Ptr2Point_3d = ^Point_3d;
Point_3d = RECORD x, y, z: Point;
END; { Rec Point_3d }
Ptr2Point_2d = ^Point_2d;
Point_2d = RECORD x, y: Point;
END; { Rec Point_2d }
Ptr2Coords = ^Coords;
Coords = RECORD c: Point_3d;
next: Ptr2Coords;
END;
VAR fin: BOOLEAN;
FP: Point_3d;
chain: Ptr2Coords;
W1,W2:^Window;
Rast1:^RastPort;
MyScreen1: ^Screen;
Rast2:^RastPort;
Rast: ^RastPort;
MyScreen2: ^Screen;
t1: IntuiText;
sin_rot_angle, cos_rot_angle: REAL;
act_pos: STRING[99];
Pointer: ^Byte; { Requiered for key-codes }
LastKey: Byte;
i: INTEGER;
pro_Res,last: Point_2d; { Result of projetion-function }
rot_res: Point_3d; { Result of rotation-func }
rot,scr_no: INTEGER;
(************************************************************************)
(* Function: *)
(* *)
(* Open Library and Screen *)
(************************************************************************)
PROCEDURE Init;
VAR i: INTEGER;
BEGIN { Init }
fin := FALSE;
Pointer := Ptr($bfec01);
LastKey := 0;
OpenLib(IntBase,'intuition.library',0);
OpenLib(GfxBase,'graphics.library' ,0);
MyScreen1:=Open_Screen(0, 0, width, height, 1, 0, 1, HIRES or GENLOCK_VIDEO,'3d-Haus');
MyScreen2:=Open_Screen(0, 0, width, height, 1, 0, 1, HIRES or GENLOCK_VIDEO,'3d-Haus');
W1:=Open_Window(0,0,width,height,1,0,$0800,Nil,MyScreen1,width,height,width,height);
W2:=Open_Window(0,0,width,height,1,0,$0800,Nil,MyScreen2,width,height,width,height);
Rast1:=W1^.RPort;
Rast2:=W2^.RPort;
Rast := Rast1;
SetRGB4(^MyScreen1^.ViewPort,0,1,1,1); { almost black }
SetRGB4(^MyScreen2^.ViewPort,0,1,1,1);
SetRGB4(^MyScreen1^.ViewPort,1,14,14,14); { almost withe }
SetRGB4(^MyScreen2^.ViewPort,1,14,14,14);
FP.x := -40; { Point of eye }
FP.y := -40;
FP.z := -40;
sin_rot_angle := sin(rot_angle);
cos_rot_angle := cos(rot_angle);
last.x := width div 2; { else undefinded }
last.y := height div 2;
scr_no := 1; { screen_number toggles between 1 and 2 }
rot := 2; { rotation axis 1,2,3 }
END; { Proc Init }
(************************************************************************)
(* Input: *)
(* *)
(* 3d-Point; call by reference *)
(************************************************************************)
(* Output: *)
(* *)
(* 3d-Point *)
(************************************************************************)
(* Function: *)
(* *)
(* rotate point by the rot_angle *)
(************************************************************************)
PROCEDURE Rotate_alfa (VAR a: Point_3d); { We change the original point }
BEGIN
a.y := a.y * cos_rot_angle - a.z * sin_rot_angle;
a.z := a.y * sin_rot_angle + a.z * cos_rot_angle;
END; { Proc Rotate_alfa }
PROCEDURE Rotate_beta (VAR a: Point_3d); { We change the original point }
BEGIN
a.x := a.x * cos_rot_angle + a.z * sin_rot_angle;
a.z := a.z * cos_rot_angle - a.x * sin_rot_angle ;
END; { Proc Rotate_beta }
PROCEDURE Rotate_gamma (VAR a: Point_3d); { We change the original point }
BEGIN
a.x := a.x * cos_rot_angle - a.y * sin_rot_angle;
a.y := a.x * sin_rot_angle + a.y * cos_rot_angle;
END; { Proc Rotate_gamma }
{ please verify the +- in r_gamma }
(************************************************************************)
(* Input: *)
(* *)
(* 3d-Point *)
(************************************************************************)
(* Output: *)
(* *)
(* 2d-Point *)
(************************************************************************)
(* Function: *)
(* *)
(* Convert py central-perspectiv *)
(************************************************************************)
PROCEDURE Projection (a: Point_3d); { result in global Pro_res }
VAR t: Point;
BEGIN { Func Projection }
{$if def debug}
WriteLn("Projection: Eingabe: (",a.x,",",a.y,",",a.z,").");
{$endif debug}
IF abs(a.y - FP.y) <1e-3
THEN t := 0
ELSE t := a.y / (2*(a.y - FP.y));
pro_res.x := 2*(a.x - t*(a.x - FP.x))+width/2;
pro_res.y := (a.z - t*(a.z - FP.z))+height/2;
{$if def debug}
WriteLn("----------- Ausgabe: (",pro_res.x,",",pro_res.y,").");
{$endif debug}
END; { Func Projection }
(************************************************************************)
(* Input: *)
(* *)
(* 2d-Points *)
(************************************************************************)
(* Function: *)
(* *)
(* Check Point for screen-dimens. cut, if neccessary *)
(************************************************************************)
PROCEDURE Check (VAR a: Point_2d);
VAR temp: Point_2d;
BEGIN
temp := a;
IF a.x < 0 THEN { right of screen }
IF (last.x-a.x)=0 THEN a.x := -1 ELSE BEGIN { check for division by 0 }
a.y := last.y - (last.y-a.y)*last.x/(last.x-a.x); a.x := 0;
END;
IF a.y >= height THEN
IF (last.y-a.y)=0 THEN a.x := -1 ELSE BEGIN
a.x := a.x - (a.x-last.x)*(last.y-height)/(a.y-last.y); a.y := height-1;
END;
IF a.x >= width THEN BEGIN
{$if def debug}
WriteLn("a.x ist zu gross: ",a.x," >= ",width);
{$endif}
IF (a.x-last.x)=0 THEN a.x := -1 ELSE BEGIN
a.y := last.y - (last.y-a.y)*(last.x-width)/(a.x-last.x); { an dieser Stelle gabs immer den /0-error }
a.x := width-1;
END;
END;
IF a.y < 0 THEN
IF (last.y-a.y)=0 THEN a.x := -1 ELSE BEGIN
a.x := a.x - (a.x-last.x)*last.y/(last.y-a.y); a.y := 0;
END; { letztes ist noch zu überprüfen }
{$if def debug}
IF(a.x <> temp.x) OR (a.y <> temp.y) THEN
WriteLn("Changes in Check-Procedure.");
{$endif debug}
last := temp;
END; { Proc Check }
(************************************************************************)
(* Input: *)
(* *)
(* Two 2d-Points (from-Coord, to-Coord) *)
(************************************************************************)
(* Function: *)
(* *)
(* Draw Line on Screen *)
(************************************************************************)
PROCEDURE Draw_line(a: Point_2d);
BEGIN
Check (a);
{$if def debug}
WriteLn("Linie nach (",a.x,",",a.y,").");
{$endif}
IF a.x <> -1 THEN Draw (Rast, round(a.x), round(a.y));
END; { Proc Draw }
(************************************************************************)
(* Input: *)
(* *)
(* 2d-Point (to-Coord) *)
(************************************************************************)
(* Function: *)
(* *)
(* Move Grafik-Cursor *)
(************************************************************************)
PROCEDURE Move_Line(a: Point_2d);
BEGIN
Check (a);
{$if def debug}
WriteLn("Bewegen nach (",a.x,",",a.y,").");
{$endif}
IF a.x <> -1 THEN Move(Rast, round(a.x), round(a.y));
END; { Proc Move_line }
(************************************************************************)
(* Input: *)
(* *)
(* Keyboard *)
(************************************************************************)
(* Function: *)
(* *)
(* change point of eye *)
(************************************************************************)
PROCEDURE Read_Change;
BEGIN
LastKey := Pointer^;
CASE LastKey OF
133: FP.x := FP.x + 1;
197: FP.x := FP.x - 1;
131: FP.y := FP.y + 1;
195: FP.y := FP.y - 1;
129: FP.z := FP.z + 1;
193: FP.z := FP.z - 1;
103: rot := 1;
101: rot := 1;
097: rot := 2;
099: rot := 2;
139: rot := 3;
201: rot := 3;
127, 117, 119: fin := TRUE;
Otherwise
END; { CASE }
CASE scr_no OF
1: BEGIN Rast:=Rast2; ScreenToFront(MyScreen1) END;
2: BEGIN Rast:=Rast1; ScreenToFront(MyScreen2) END
END;
scr_no := 3-scr_no;
SetAPen(Rast,0);
RectFill(Rast,0,0,Width-1,Height-1);
SetAPen(Rast,1);
END; { Proc Read_Changes }
(************************************************************************)
(* Input: *)
(* *)
(* Chain of 3d-points *)
(************************************************************************)
(* Function: *)
(* *)
(* Calculate and Draw 3d-points *)
(************************************************************************)
PROCEDURE Calc_Draw (root: Ptr2Coords);
BEGIN
WHILE root <> NIL DO
BEGIN
IF root^.c.x = -1 THEN
BEGIN
root := root^.next;
CASE rot OF
1: Rotate_alfa (root^.c);
2: Rotate_beta (root^.c);
3: Rotate_gamma(root^.c);
ELSE; END; { case }
Projection (root^.c);
Move_Line(pro_res);
END
ELSE BEGIN
CASE rot OF
1: Rotate_alfa (root^.c);
2: Rotate_beta (root^.c);
3: Rotate_gamma(root^.c);
ELSE; END; { case }
Projection(root^.c);
Draw_Line(pro_res);
END;
root := root^.next;
END; { WHILE }
END; { Proc Calc_Draw }
(************************************************************************)
(* Input: *)
(* *)
(* File of coords of object *)
(************************************************************************)
(* Output: *)
(* *)
(* Root of chain *)
(************************************************************************)
(* Function: *)
(* *)
(* read file from extern device *)
(************************************************************************)
FUNCTION Read_Coords: Ptr2Coords;
VAR f: FILE OF CHAR;
old_coord, result, temp: Ptr2Coords;
BEGIN
New (result);
WITH result^.c DO
BEGIN
x := -1;
y := 0;
z := 0;
END; { WITH }
old_coord := result;
Reset (f, file_Name);
IF EoF(f) THEN Error ("File not Found.");
WHILE NOT EoF(f) DO
BEGIN
New (temp);
WITH temp^.c DO
BEGIN
ReadLn (f, x, y, z);
{$if def debug}
WriteLn("Gelesene Coordinaten: (",x,",",y,",",z,").");
{$endif}
END; { WITH }
old_coord^.next := temp;
old_coord := temp;
END; { WHILE }
temp^.next := NIL; { End of chain }
Read_Coords := result;
END; { Func Read_Coords }
(************************************************************************)
(* Function: *)
(* *)
(* Close libraries and screen *)
(************************************************************************)
PROCEDURE Close_(list:Ptr2Coords);
VAR temp: Ptr2Coords;
BEGIN
WHILE (list <> NIL) DO
BEGIN
temp := list^.next;
dispose (list);
list := temp;
END; { WHILE }
Close_Screen(MyScreen1);
Close_Screen(MyScreen2);
CloseLib(intbase);
CloseLib(GfxBase);
END;
(************************************************************************)
(* Input: *)
(* *)
(* *)
(************************************************************************)
(* Output: *)
(* *)
(* *)
(************************************************************************)
(* Function: *)
(* *)
(* *)
(************************************************************************)
BEGIN { Main }
Init;
chain := Read_Coords;
REPEAT
Calc_Draw (chain);
Read_Change;
act_pos := '('+RealStr(FP.x,0)+','+RealStr(FP.y,0)+','+RealStr(Fp.z,0)+')';
t1:=IntuiText(1,0,1,0,0,Nil,act_pos,Nil);
PrintIText (Rast1, ^t1, 10,190);
PrintIText (Rast2, ^t1, 10,190);
UNTIL fin;
Close_(chain);
END.